#!/usr/bin/env jython
# -*- coding: utf-8 -*-
import sys
sys.setdefaultencoding("utf-8")

import os
'''Python standart lib path'''

sys.setdefaultencoding("utf-8")
sys.path.append('/usr/lib/python2.7') 
sys.path.append('/usr/lib/python2.7/plat-linux2') 
sys.path.append('/usr/lib/python2.7/lib-tk')
sys.path.append('/usr/lib/python2.7/lib-old')
sys.path.append('/usr/lib/python2.7/lib-dynload')
sys.path.append('/usr/local/lib/python2.7/dist-packages')
sys.path.append('/usr/lib/python2.7/dist-packages')
sys.path.append('/usr/lib/python2.7/dist-packages/PIL')
sys.path.append('/usr/lib/pymodules/python2.7/gtk-2.0')
sys.path.append('/usr/lib/python2.7/dist-packages/gst-0.10')
sys.path.append('/usr/lib/python2.7/dist-packages/gtk-2.0')
sys.path.append('/usr/lib/pymodules/python2.7')
sys.path.append('/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode')

'''Java external jars'''
sys.path.append('opencsv-2.3.jar')

from javax.swing.event import ListSelectionEvent,ListSelectionListener
from javax.swing import JFrame,JButton,JMenuBar,JMenu,JMenuItem,JOptionPane, BoxLayout
from javax.swing import JFileChooser, JLabel,JTextField, JPanel,JButton, JList, JScrollPane, Box
from javax.swing.filechooser import FileFilter, FileNameExtensionFilter
from java.awt import FlowLayout,GridLayout
from java.lang import System
from httpRetriver import HttpRetriver
from java.lang import String

from au.com.bytecode.opencsv import CSVReader,CSVWriter
from java.io import FileReader,FileWriter
from SQLloader import JConverter
from Statistics import Statistics
from htmlGenerator import HTMLGenerator



class App(JFrame):

	'''
	Aplicacao grafica Jpython recurendo a biblioteca swing
	'''
	def __init__(self):
		JFrame.__init__(self,"JythonApp",size = (780, 654),defaultCloseOperation=JFrame.EXIT_ON_CLOSE)
		self.__setMenus()
		self.__panel = JPanel()
		self.__panel.setLayout(None)
		self.add(self.__panel)
		self.visible = True
		self.__headers = ["Código do Docente","Nome","Último Grau","Curso","Categoria","Regime de Tempo","Ano Lectivo","Tipo de Estabelecimento","Nome do Estabelecimento"]
		self.__data = []

	'''
	Cria os menus e adiciona-os ao Jframe
	'''
	def __setMenus(self):
		menubar = JMenuBar()

		menuFile = JMenu("File")
		soap = JMenuItem("Get html info", actionPerformed=self.__htmlInfo)
		sendToDB = JMenuItem("Send csv to data base", actionPerformed=self.__sendToDB)
		close = JMenuItem("Exit", actionPerformed=self.__exit)

		menuView = JMenu("View")
		Statistics = JMenuItem("Statistics",actionPerformed=self.__setStatView)

		menuFile.add(soap)
		menuFile.add(sendToDB)
		menuFile.add(close)
		menubar.add(menuFile)

		menuView.add(Statistics)
		menubar.add(menuView)
		self.setJMenuBar(menubar)
	'''
	Sai da aplicacao via java
	'''
	def __exit(self,event):
		System.exit(0)


	'''
	Cria a vista de escolha de estatistica, evento do menu statistics no menu view
	'''
	def __setStatView(self,event):
		self.__panel.removeAll()

		self.__setDBAndTableNames()
		
		b1 = JButton("Techers per establishment per year",actionPerformed=self.__setListView1)
		b2 = JButton("Techers per establishment per catgory per year",actionPerformed=self.__setSeach2)
		b3 = JButton("Techers per establishment per degree per year",actionPerformed=self.__setSeach3)
		
		self.__panel.add(b1)
		self.__panel.add(b2)
		self.__panel.add(b3)
		b1size = b1.getPreferredSize()
		b2size = b2.getPreferredSize()
		b3size = b3.getPreferredSize()
		b1.setBounds(20,80,b1size.width,b1size.height)
		b2.setBounds(20,110,b2size.width,b2size.height)
		b3.setBounds(20,140,b3size.width,b3size.height)
		self.__refreshFrame()

	'''	
	Faz o refresh da view tornado o frame invisivel e depois visivel
	'''	
	def __refreshFrame(self):
		self.setVisible(False)
		self.setVisible(True)
	
	'''
	Atribui ao atributo self.__data todos os registo da bd
	'''
	def __getSQLData(self):
		if not(self.__data):
			sql = JConverter(self.__db.getText(),self.__table.getText())
			self.__data = sql.getValues()
			sql.closeDB()

	'''
	Dependendo da escolha cria uma estatistica para o atributo self.dat
	'''
	def __getStat(self):
		self.__dat = {}
		self.__stat = Statistics(self.__data)
		if(self.__search == 1):						
			self.__dat = self.__stat.getTeachersPerEstablisment()
		if(self.__search == 2):			
			self.__dat = self.__stat.getTeachersEstYearCat()
		if(self.__search == 3):
			self.__dat = self.__stat.getTeachersEstYearDegree()		
	'''
	Cria uma lista de anos a partir dos dados em self.dat(Estistica)
	'''	
	def __getYears(self):
		years = []
		for year,est in self.__dat.iteritems():
			years.append(year)
		return years

	'''
	Cria uma JList com determinadas dimensoes w,h e posicao x,y com o items e evento onChange,
	adicionando ao container
	'''
	def __createList(self,container,x,y,w,h,items,onChange):
		if(onChange):
			lis = JList(items,valueChanged=onChange)
		else:
			lis = JList(items)
		js = JScrollPane(lis)
		container.add(lis)
		container.add(js)
		js.getViewport().add(lis)
		lis.setBounds(x,y,w,h)
		js.setBounds(x,y,w,h)
		return lis

	'''
	Cria uma JLabel com a posicao x,y com o texto text,
	adicionando ao container
	'''
	def __createLabel(self,container,text,x,y):
		label = JLabel(text)
		size = label.getPreferredSize()
		label.setBounds(x,y,size.width + 50,size.height)
		container.add(label)
		return label
			
	'''
	Cria uma JButton na posicao x,y com o texto text e acção action,
	adicionando ao container
	'''
	def __createButton(self,container,text,x,y,action):
		b1 = JButton(text,actionPerformed=action)		
		container.add(b1)
		b1size = b1.getPreferredSize()
		b1.setBounds(x,y,b1size.width,b1size.height)
		return b1
	
	'''
	atribui 3 ao atributo self.search e chama o metodo self.listview2
	'''
	def __setSeach3(self,event):
		self.__search = 3
		self.__setListView2()

	'''
	atribui 2 ao atributo self.search e chama o metodo self.listview2
	'''
	def __setSeach2(self,event):
		self.__search = 2
		self.__setListView2()
	
	'''
	Evento que manda o conteudo da lista4 para um ficheiro csv
	'''
	def __teachresToCSV(self,event):
		try:
			fil = self.__chooseFile("CSV files", ["csv"])
			csvW = CSVWriter( FileWriter(fil),',')
			csvW.writeNext([x.decode("UTF-8") for x in self.__headers])
			for row in self.__level4:			
				csvW.writeNext(row)
			csvW.close()
		except:
			pass
	'''
	Cria a visualização de lista 1 composta por 3 listas e tres labels
	'''
	def __setListView1(self,event):
		self.__panel.removeAll()
		self.__getSQLData()
		self.__search = 1
		self.__getStat()
		years = self.__getYears()
		self.__list1 = self.__createList(self.__panel,10,10,372,100,years,self.__list1_EVT)
		self.__list1label = self.__createLabel(self.__panel,"Years: "+str(len(years)),10,110)

		self.__list2 = self.__createList(self.__panel,398,10,372,100,[],self.__list2_EVT)
		self.__list2label = self.__createLabel(self.__panel,'Establishments:',398,110)

		self.__list4 = self.__createList(self.__panel,10,150,760,250,[],self.__list4_EVT)
		self.__list4label = self.__createLabel(self.__panel,'Number of teachers: ',10,410)
		self.__createButton(self.__panel,"Create html site",10,430,self.__createSite)
		self.__btCSV = self.__createButton(self.__panel,"Dump teachers to csv",160,430,self.__teachresToCSV)
		self.__btCSV.setEnabled(False)
		self.__statCSV = self.__createButton(self.__panel,"Dump statistics to csv",348,430,self.__statToCSV)
		self.__statCSV.setEnabled(False)
		self.__refreshFrame()
	
	'''
	Cria a visulizaçao de listas 2 com quatro lista e quatro labels
	'''
	def __setListView2(self):
		self.__panel.removeAll()
		self.__getSQLData()
		self.__getStat()
		if(self.__search == 2):
			catOrDegree = 'Catgory: '
		else:
			catOrDegree = 'Degree: '
		years = self.__getYears()
		self.__list1 = self.__createList(self.__panel,10,10,247,100,years,self.__list1_EVT)
		self.__list1label = self.__createLabel(self.__panel,"Years: "+str(len(years)),10,110)

		self.__list2 = self.__createList(self.__panel,267,10,247,100,[],self.__list2_EVT)
		self.__list2label = self.__createLabel(self.__panel,'Establishments: ',267,110)

		self.__list3 = self.__createList(self.__panel,523,10,247,100,[],self.__list3_EVT)
		self.__list3label = self.__createLabel(self.__panel,catOrDegree,523,110)

		self.__list4 = self.__createList(self.__panel,10,150,760,250,[],self.__list4_EVT)
		self.__list4label = self.__createLabel(self.__panel,'Number of teachers: ',10,410)
		self.__createButton(self.__panel,"Create html site",10,430,self.__createSite)
		self.__btCSV = self.__createButton(self.__panel,"Dump teachers to csv",160,430,self.__teachresToCSV)
		self.__btCSV.setEnabled(False)
		self.__statCSV = self.__createButton(self.__panel,"Dump statistics to csv",348,430,self.__statToCSV)
		self.__statCSV.setEnabled(False)
		self.__refreshFrame()

	'''
	Guarda os valores da estatistica no ficheiro csv
	'''
	def __statToCSV(self,event):
		try:
			fil = self.__chooseFile("CSV files", ["csv"])
			csvW = CSVWriter( FileWriter(fil),',')
			csvW.writeNext([x.decode("UTF-8") for x in self.__legend])
			csvW.writeNext([str(x) for x in self.__values])
			csvW.close()
		except:
			pass

	'''
    Evento de single click lista 1, dependendo da selecao actualiza a lista 2
    '''	
	def __list1_EVT(self,event):
		self.__sellist1 = self.__list1.getSelectedValue()
		self.__level2 = self.__dat[self.__sellist1]
		scools = []
	
		for scool in self.__level2.iterkeys(): 
			scools.append(scool) 
		scools.sort()       
		self.__list2.setListData(scools)
		count = len(scools)
		self.__list2label.setText("Establishment: " + str(count))
        

		
	'''
    Evento de single click lista 2, actualiza lista 3 ou 4 dependendo da self.search (Escolha de estatistica)
    '''	
	def __list2_EVT(self,event):
		try:
			self.__sellist2 = self.__list2.getSelectedValue()            
			if(self.__search == 2 or self.__search == 3):
				self.__level3 = self.__level2[self.__sellist2]        

				CatgoryORDegrees = []

				for catgoryODegree in self.__level3.iterkeys(): 
				    CatgoryORDegrees.append(catgoryODegree)  
				CatgoryORDegrees.sort()              
				self.__list3.setListData(CatgoryORDegrees)
				                
				if(self.__search == 2):                
				    word="Catgory: "
				else:
				    word="Degree: "
				    
				count = len(CatgoryORDegrees)
				self.__list3label.setText(word + str(count))
			else:
				self.__level4 = self.__level2[self.__sellist2]        
				profs = []

				for prof in self.__level4: 
				    profs.append(prof) 
				techers,count = self.__setStringList(profs)
				self.__list4.setListData(techers)
			self.__list4label.setText("Number of teachers: " + str(count))
		except: 
			pass	
		self.__legend = []
		self.__values = []		
		self.__legend, self.__values = self.__stat.JTreeLevelsSeach(self.__sellist2,self.__dat)
		self.__statCSV.setEnabled(True)
		self.__statList = self.__createList(self.__panel,10,460,150,100,[],'')
		self.__setStatList()		
		
	'''
	Actualiza a lista de estatistica do vaçlor selecionado
	'''	
	def __setStatList(self):
		names = []
		self.__statList.setListData(names)
		for x in range(0,len(self.__legend)):
			names.append(str(self.__legend[x]) + '->' + str(self.__values[x]))
		self.__statList.setListData(names)

	'''
    Evento de single click lista 3, actualiza lista 4
    '''	
	def __list3_EVT(self,event):
		try:
		    self.__sellist3 = self.__list3.getSelectedValue()              
		    self.__level4 = self.__level3[self.__sellist3]        
		    profs = []
		  
		    for prof in self.__level4: 
		        profs.append(prof) 
		    techers,count = self.__setStringList(profs)
		    self.__list4.setListData(techers)
		    self.__list4label.setText("Number of teachers: " + str(count))
		except:
		    pass
		self.__legend, self.__values = self.__stat.JFourLevelsSeach(self.__sellist3,self.__sellist2,self.__dat)
		self.__statCSV.setEnabled(True)
		self.__statLabel = self.__createLabel(self.__panel,'statistics',10,460)
		self.__setStatList()
	'''
	Activa o buttao send to csv
	'''
	def __list4_EVT(self,event):
		self.__btCSV.setEnabled(True)
		pass
	
	'''
	Recebe uma lista e converte os elementos numa unica string
	'''
	def __setStringList(self,reg):
	    profs = []
	    count = len(reg)
	    for teacher in reg:
	        text = ''
	        for row in teacher:
	            text += ' - ' + row
	        profs.append(text)
	    profs.sort()
	    return profs,count	
	
	'''
	remove os elementos do painel, pede o nome de um ficheiro e coloca a vista de db 
	'''
	def __sendToDB(self, event):
		self.__panel.removeAll()
		self.__csvFile = self.__chooseFile("CSV files", ["csv"])
		self.__setDBview()

	'''
	Vista de introducao de dados de db
	'''
	def __setDBAndTableNames(self):
		dblabel = JLabel("Data base: ")
		self.__db = JTextField("reb")
		self.__panel.add(dblabel)
		self.__panel.add(self.__db)

		dbLabelsize = dblabel.getPreferredSize()
		
		
		tablelabel = JLabel("Table: ")
		self.__table = JTextField("reb10")
		self.__panel.add(tablelabel)
		self.__panel.add(self.__table)

		
		tableLabelsize = tablelabel.getPreferredSize()

		dblabel.setBounds(20,50,dbLabelsize.width,dbLabelsize.height)
		self.__db.setBounds(100,50,80,20)

		tablelabel.setBounds(180,50,tableLabelsize.width,tableLabelsize.height)
		self.__table.setBounds(230,50,80,20)
	
	'''
	remove elementos do painel, mostra label com o csv a descarregar para a base de dados,
	e mostra o buttao para iniciar a descarga
	'''
	def __setDBview(self):	
		self.__panel.removeAll()
		csv = JLabel("CSV file: " + str(self.__csvFile))
		csvsize =csv.getPreferredSize()
		csv.setBounds(20,20,csvsize.width,csvsize.height)

		self.__panel.add(csv)
		self.__setDBAndTableNames()
		dump = JButton("Dump to Data Base",actionPerformed=self.__sendToSQL)

		self.__panel.add(dump)		
		dumpsize = dump.getPreferredSize()
		dump.setBounds(20,80,dumpsize.width,dumpsize.height)
		self.__refreshFrame()
	
	'''
	Envia dados para a base de dados
	'''
	def __sendToSQL(self,event):
		h,data = self.__getData()
		sql = JConverter(self.__db.getText(),self.__table.getText())
		sql.createDB(h)
		row = 0
		for line in data:
			sql.insertDB(line)
			print row
			row += 1			
		self.__createLabel(self.__panel,str(row)+" :Regists created",200,90)
		self.__refreshFrame()
		pass

	'''
	Retira campos do csv e dados
	'''
	def __getData(self):	        
	    reader = CSVReader( FileReader(self.__csvFile))
	    lines = reader.readAll()
	    data = []
	    h=[]
	    rownum = -1
	        
	    for row in lines:
	        if(rownum == -1):
	            h = row
	            rownum = 0
	        else:
	            data.append(row)
	    return h,data
	          
	'''
	Retira dados de uma url e mostra no panel sob forma de JLabels
	'''
	def __htmlInfo(self,event):	
		try:	
			self.__panel.removeAll()
			vertical = Box.createVerticalBox()
			url = JOptionPane.showInputDialog(self,"Insert a page url","http://www.rebides.oces.mctes.pt/Rebides09/");	
			http = HttpRetriver(url)
			vertical.add(JLabel("There are " + str(http.getTagCount("h1")) + " <h1> tags"))
			vertical.add(JLabel("There are " + str(http.getTagCount("h2")) + " <h2> tags"))
			vertical.add(JLabel("There are " + str(http.getTagCount("h3")) + " <h3> tags"))
			vertical.add(JLabel("There are " + str(http.getTagCount("div")) + " <div> tags"))
			vertical.add(JLabel("There are " + str(http.getTagCount("ul")) + " <ul> tags"))
			vertical.add(JLabel("There are " + str(http.getTagCount("ol")) + " <ol> tags"))
			self.__panel.add(vertical)
			vSize = vertical.getPreferredSize()
			vertical.setBounds(10,10,vSize.width, vSize.height)
			self.__refreshFrame()	
		except:
			pass

	'''
	Mostra caixa de dialogo para escolha de ficheiro
	'''
	def __chooseFile(self,text,ext):	
		fChooser = JFileChooser(".")

		filt = FileNameExtensionFilter(text, ext)
		fChooser.addChoosableFileFilter(filt)

		ret = fChooser.showDialog(self, "Select file")
		if (ret == JFileChooser.APPROVE_OPTION) :
		    File = fChooser.getSelectedFile()
		    return File
		else:
			return ''

	'''
	Cria um ficheiro html com um tag h1, na directoria especificada
	'''    
	def __createHtmlfile(self,directory,h1):
		try:
		    directory = self.__clearPoints(directory)
		    htmlfile = HTMLGenerator(directory + '.html')
		    htmlfile.printH1(h1)
		    htmlfile.lineBR()
		    print "File:    "+directory		
		    return htmlfile 
		except:
			pass

	'''
	Addiciona um link a um ficheiro html
	''' 
	def __addHTMLLink(self,ref,name,link):
		try:
		    link = self.__clearPoints(link)
		    ref.link(name,link + '.html')
		    ref.lineBR() 
		    print"link: "+name
		except:
			pass

	'''
	Filtra uma string subtituindo os pontos por underscorees
	'''
	def __clearPoints(self,string):
	    return string.replace(".","_")

	'''
	Filtra uma string subtituindo os baras por underscorees
	'''
	def __clearBars(self,string):
	    return string.replace("/","_")

	'''
	Gera o site dependendo da estatistica
	'''      
	def __createSite(self,event):
	    level3 = self.__setDirectory()
	     
	    index = self.__createHtmlfile('index','Years')
	    
	    for year,scools in self.__dat.iteritems(): 
	        year = self.__clearBars(year)
	        self.__addHTMLLink(index,year, 'year/' + year)                      
	        fyear = self.__createHtmlfile('year/' + year ,'Establishments')   
	                 
	        for scool,teachers in scools.iteritems():
	            scool = self.__clearBars(scool)
	            self.__addHTMLLink(fyear,scool,'scools/' + scool)                
	            fscool = self.__createHtmlfile('year/scools/' + scool,level3)
	            
	            if(self.__search == 1):                   
	                fscool.makeTable(self.__headers,teachers)
	                fscool.CloseFile()
	            else:
	                for catOrDeg,teach in teachers.iteritems():
	                    catOrDeg = self.__clearBars(catOrDeg)
	                    catOrDeg = self.__clearPoints(catOrDeg)
	                    if(self.__search == 2):
	                        level4 = 'Catgory/'
	                    if(self.__search == 3):
	                        level4 = 'Degree/'   
	                    self.__addHTMLLink(fscool, catOrDeg, level4 + catOrDeg)                       
	                    fcatOrDegree = self.__createHtmlfile('year/' +'scools/' + level4 + catOrDeg,catOrDeg)
	                   
	                    fcatOrDegree.makeTable(self.__headers,teach)
	                    fcatOrDegree.CloseFile()
	                fscool.CloseFile()
	        fyear.CloseFile()
	    index.CloseFile()

	def __setDirectory(self):
	   	try:
		    if(self.__search == 1): 
		        level3 = 'Teachers'  
		        self.__MKDIR("year/" + "scools/"+level3+"/")         
		        pass
		    elif(self.__search == 2):
		        level3 = 'Catgory' 
		        self.__MKDIR("year/" + "scools/"+level3+"/")
		        pass
		    elif(self.__search == 3):
		        level3 = 'Degree' 	        
		    	self.__MKDIR("year/" + "scools/"+level3+"/") 
		    return level3
		except:
			pass
	'''
	Cria uma hieraquia de directorios
	'''
	def __MKDIR(self,directory):
	    os.makedirs(directory)


if __name__ == "__main__":	
	App()	
	



